package Underworld_Survival;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import static Underworld_Survival.AttributeType.*;
import static Underworld_Survival.Game.*;
import static Underworld_Survival.GameOutput.Template.*;

public class Player extends Role{
    private int currentAgi;//当前能量
    private int baseMaxAgi;//基础能量上限
    private int bonusMaxAgi=0;//加成能量上限
    private int totalMaxAgi;//总能量上限
    public Bag bag;//背包


    public Player() {
        effectManager=new EffectManager();
        buff=new ArrayList<>();
        ability=new Ability();
        weaponSlot=new WeaponSlot();
        armorSlot=new ArmorSlot();
        shoeSlot=new ShoeSlot();
        bag=new Bag();
    }
    public Player(String name,int baseMaxHP,int baseMaxAgi,int baseStr, int baseDef, int baseEP) {
        super(name,baseMaxHP,baseStr,baseDef,baseEP);
        baseCritRate=0.15f;
        totalCritRate=baseCritRate;
        baseCritMultiplier=1.4f;
        totalCritMultiplier=baseCritMultiplier;
        currentAgi=baseMaxAgi;
        this.baseMaxAgi=baseMaxAgi;
        totalMaxAgi=baseMaxAgi;
        bag=new Bag();
    }


    public boolean canUseSkill(Skill skill){
        return currentAgi>=skill.getConsumeAgi();
    }
    public void learnSkill(Skill skill){
        //技能重复
        for(int i=0;i<ability.getActiveSkill().size();i++){
            if(ability.getActiveSkill().get(i).getSkillName().equals(skill.getSkillName())){
                System.out.println("这个技能你早已会了，无需再学。");
                return;
            }
        }
        //技能数未满5个(默认自带一个绝地求生)，直接学习
        if(ability.getActiveSkill().size()<=4&&ability.getActiveSkill().size()>=1){
            ability.getActiveSkill().add(skill);
        }
        else if(ability.getActiveSkill().size()==5){//技能满了（达到了5个）
            ability.showActiveSkill();
            System.out.println("技能已满，你的选择是？"+'\n'+"1.替换已有技能         2.放弃学习新技能");
            int select=inputCheck(1,2);
            if(select==1){
                ability.showActiveSkill();
                System.out.println("请选择你要替换的技能：");
                int select1=inputCheck(1,4);
                ability.getActiveSkill().set(select1,skill);
                System.out.println("你成功学会了技能："+skill.getSkillName());
            }else{
                System.out.println("我已文武双全，无需再学！");
            }
        }else{
            throw new IllegalStateException("拥有非法个数的技能");
        }
    }

    //使用一次性补给品(食物，卷轴，其他道具)，触发效果，然后从背包中移除
    public void useSupply(Item supply){
        if(supply instanceof Food){
            bag.getFood().remove(supply);
            ((Food)supply).applyFoodEffect(this);
        }else if(supply instanceof Scroll){
            bag.getScroll().remove(supply);
            ((Scroll)supply).applyScrollEffect(this);
        }else if(supply instanceof OtherItem){
            bag.getOtherItem().remove(supply);
            ((OtherItem)supply).applyOtherItemEffect(this);
        }
        else{
            throw new IllegalStateException("使用非法类型");
        }
    }

    //获得任何游戏道具（食物，卷轴，装备，道具）
    public void obtainItem(Item item){
        if(item instanceof Food){
            bag.getFood().add((Food)item);
        }else if(item instanceof Scroll){
            bag.getScroll().add((Scroll) item);
        }else if(item instanceof OtherItem){
            bag.getOtherItem().add((OtherItem) item);
        }else if(item instanceof Weapon){
            if(!this.weaponSlot.hasWeapon()){
                gameOutput.print(GameOutput.MsgType.SYSTEM,item.getName()+"已自动装备！");
                equipWithEquipment((Weapon)item);
            }else{
                bag.getWeapon().add((Weapon) item);
            }
        }else if(item instanceof Armor){
            if(!this.armorSlot.hasArmor()){
                gameOutput.print(GameOutput.MsgType.SYSTEM,item.getName()+"已自动装备！");
                equipWithEquipment((Armor)item);
            }else{
                bag.getArmor().add((Armor) item);
            }
        }else if(item instanceof Shoe){
            if(!this.shoeSlot.hasShoe()){
                gameOutput.print(GameOutput.MsgType.SYSTEM,item.getName()+"已自动装备！");
                equipWithEquipment((Shoe)item);
            }else{
                bag.getShoe().add((Shoe) item);
            }
        }
    }
    public <T extends Item> void sellItem(T item){
        if(item instanceof Food){
            bag.getFood().remove(item);
        }else if(item instanceof Scroll){
            bag.getScroll().remove(item);
        }else if(item instanceof OtherItem){
            bag.getOtherItem().remove(item);
        }else if(item instanceof Weapon){
            bag.getWeapon().remove(item);
        }else if(item instanceof Armor){
            bag.getArmor().remove(item);
        }else if(item instanceof Shoe){
            bag.getShoe().remove(item);
        }else{
            throw new IllegalStateException("出售非法类型物品！");
        }
        rewardGold(item.priceOfSelling);
        GameOutput.ShowPlayer.estate();
    }
    //装备的装备与卸下
    public void equipWithEquipment(Equipment equipment){
        if(equipment==null){
            return;
        }
        if(equipment instanceof Weapon){
            if(weaponSlot.hasWeapon()){
                removeEquipment(weaponSlot.getEquippedItem());
            }
            ((Weapon)equipment).equip(this);//武器处于装备状态，触发武器装备的效果
            weaponSlot.equip(((Weapon)equipment));//武器槽装上这把武器
            bag.getWeapon().remove(((Weapon)equipment));//背包里面移除这把武器
        }else if(equipment instanceof Armor){
            if(armorSlot.hasArmor()){
                removeEquipment(armorSlot.getEquippedItem());
            }
            ((Armor)equipment).equip(this);//防具处于装备状态，触发防具装备的效果
            armorSlot.equip(((Armor)equipment));//防具槽装上这把防具
            bag.getArmor().remove(((Armor)equipment));//背包里面移除这把防具
        }else if(equipment instanceof Shoe){
            if(shoeSlot.hasShoe()){
                removeEquipment(shoeSlot.getEquippedItem());
            }
            ((Shoe)equipment).equip(this);//鞋子处于装备状态，触发鞋子装备的效果
            shoeSlot.equip(((Shoe)equipment));//鞋子槽装上这把防具
            bag.getShoe().remove(((Shoe)equipment));//背包里面移除这双鞋子
        }else{
            throw new IllegalStateException("装备非法类型的装备！");
        }
    }
    public void removeEquipment(Equipment equipment){
        if(equipment==null){
            return;
        }
        if(equipment instanceof Weapon){
            weaponSlot.unequip();//武器槽卸下这把武器
            ((Weapon)equipment).unequip(this);//将武器装备的效果移除
            bag.getWeapon().add(((Weapon)equipment));//背包里获得这把武器
        }else if(equipment instanceof Armor){
            armorSlot.unequip();//防具槽卸下这把武器
            ((Armor)equipment).unequip(this);//将防具装备的效果移除
            bag.getArmor().add(((Armor)equipment));//背包里获得这把防具
        }else if(equipment instanceof Shoe){
            shoeSlot.unequip();//鞋子槽卸下这把武器
            ((Shoe)equipment).unequip(this);//将鞋子装备的效果移除
            bag.getShoe().add(((Shoe)equipment));//背包里获得这把鞋子
        }else{
            throw new IllegalStateException("卸除非法类型的装备！");
        }
    }


    public void rewardGold(int gold){bag.setGold(bag.getGold()+gold);}//获得金币
    public boolean useGold(int gold){//使用金币
        if(bag.getGold()-gold<0){
            System.out.println("金币不足"+gold+"个！");
            return false;
        }else{
            bag.setGold(bag.getGold()-gold);
            GameOutput.ShowPlayer.estate();
            return true;
        }
    }
    public void rewardDiamond(int diamond){bag.setDiamond(bag.getDiamond()+diamond);}//获得钻石
    public boolean useDiamond(int diamond){//使用钻石
        if(bag.getDiamond()-diamond<0){
            System.out.println("钻石不足"+diamond+"个！");
            return false;
        }else{
            bag.setDiamond(bag.getDiamond()-diamond);
            GameOutput.ShowPlayer.estate();
            return true;
        }
    }

    //修改各种属性，不包括当前血量和当前能量
    public void modifyAttributes(Map<AttributeType, Float> modifiers,boolean isPrint) {
        AtomicBoolean is = new AtomicBoolean(false);
        Shoe shoe=shoeSlot.getEquippedItem();
        modifiers.forEach((type,value)->{
            if(type.equals(BASE_STR)||type.equals(BASE_DEF)||type.equals(BASE_EP)||
                    type.equals(BASE_CRITRATE)||type.equals(BASE_CRITMULTIPLIER)){
                if(shoeSlot.hasShoe()){
                    if(shoe.getName().equals("<魔法靴>"));{
                        removeEquipment(shoe);
                        is.set(true);
                    }
                }
            }
        });
        modifiers.forEach((type, value) -> {
            switch (type) {
                // 基础属性（只能增加）
                case BASE_MAXHP:
                    this.baseMaxHP += Math.max(0, value.intValue());//value.intValue()由于value是一个浮点型，这了取值整数部分
                    break;
                case BASE_MAXAGI:
                    this.baseMaxAgi += Math.max(0, value.intValue());
                    break;
                case BASE_STR:
                    this.baseStr += Math.max(0, value.intValue());
                    break;
                case BASE_DEF:
                    this.baseDef += Math.max(0, value.intValue());
                    break;
                case BASE_EP:
                    this.baseEP += Math.max(0, value.intValue());
                    break;
                // 加成属性（可正可负）
                case BONUS_MAXHP:
                    this.bonusMaxHP += value.intValue();
                    break;
                case BONUS_MAXAGI:
                    this.bonusMaxAgi += value.intValue();
                    break;
                case BONUS_STR:
                    this.bonusStr += value.intValue();
                    break;
                case BONUS_DEF:
                    this.bonusDef += value.intValue();
                    break;
                case BONUS_EP:
                    this.bonusEP += value.intValue();
                    break;
                // 特殊属性处理
                case BASE_CRITRATE:
                    this.baseCritRate = clamp(value + this.baseCritRate, 0f, 1f);//暴击率的增加值最小0，最大1
                    break;
                case BONUS_CRITRATE:
                    this.bonusCritRate = clamp(value + this.bonusCritRate, -1f, 1f);
                    break;
                case BASE_CRITMULTIPLIER:
                    this.baseCritMultiplier = clamp(value + this.baseCritMultiplier, 0f, 3f);
                    break;
                case BONUS_CRITMULTIPLIER:
                    this.bonusCritMultiplier = clamp(value + this.bonusCritMultiplier, -3f, 3f);
                    break;
            }
            if(isPrint) {
                if (value < 0) {
                    gameOutput.print(GameOutput.MsgType.DECREASE, "%s降低%.2f   ", type.getDescription(), -value);
                } else {
                    gameOutput.print(GameOutput.MsgType.INCREASE, "%s提升%.2f   ", type.getDescription(), value);
                }
            }
        });
        if(is.get()){
            equipWithEquipment(shoe);
        }
        System.out.println();
        updateAttribute();//增加完后更新属性
    }

    public void updateAttribute(){
        totalMaxHP=bonusMaxHP+baseMaxHP;
        totalMaxAgi=bonusMaxAgi+baseMaxAgi;
        totalStr=bonusStr+baseStr;
        totalDef=bonusDef+baseDef;
        totalEP=bonusEP+baseEP;
        totalCritRate=baseCritRate+bonusCritRate;
        totalCritMultiplier=baseCritMultiplier+bonusCritMultiplier;
    }

    //能量,血量的消耗与恢复
    public void refillHP(int value){
        if(currentHP+value>totalMaxHP){
            currentHP=totalMaxHP;
        }else{
            currentHP+=value;
        }
        gameOutput.println(GameOutput.MsgType.RECOVER,pRefillHP,value,currentHP,totalMaxHP);
    }
    public void reduceHP(int value){
        if(currentHP<value){
            currentHP=0;
        }else{
            currentHP-=value;
        }
        if(currentHP<=0){
            for(int i=0;i<this.bag.getOtherItem().size();i++){
                if(bag.getOtherItem().get(i).getName().equals("{回生药}")){
                    gameOutput.println(GameOutput.MsgType.DIE,"你已经死亡了！游戏结束！但真的吗？");
                    gameOutput.println(GameOutput.MsgType.DIE,"当然不是！背包里的回生药竟然起了作用，你又满血复活了！"+'\n'+
                            "！！！！！！！！！！消耗道具{回生药}，游戏继续！！！！！！！！！！"+'\n'+'\n'+
                            "重生之我在地牢杀敌！");
                    useSupply(bag.getOtherItem().get(i));
                    return;
                }
            }
            gameOutput.println(GameOutput.MsgType.DIE,"我...我不甘心！\n生命值为0，游戏结束！");
            player=new Player("",100,30,15,5,5);
            stage=0;
            stageOfMerchantAppears[0]=0;
            try {
                GameDataSaveManager.saveGame(player);
            } catch (IOException e) {
                System.err.println("保存游戏数据时出现错误：" + e.getMessage());
                e.printStackTrace();
            }
            System.exit(0);
        }
    }
    public void refillAgi(int value){
        if(currentAgi+value>totalMaxAgi){
            currentAgi=totalMaxAgi;
        }else{
            currentAgi+=value;
        }
        gameOutput.println(GameOutput.MsgType.RECOVER,refillAgi,value,currentAgi,totalMaxAgi);
    }
    public void reduceAgi(int value){
        if(currentAgi<value){
            currentAgi=0;
        }else{
            currentAgi-=value;
        }
        if(value>0){
            gameOutput.println(GameOutput.MsgType.REDUCE,consumeAgi,value);
        }
    }

    //各种属性的getter,setter
    public int getCurrentAgi() {return currentAgi;}
    public void setCurrentAgi(int currentAgi) {this.currentAgi = currentAgi;}
    public int getBaseMaxAgi() {return baseMaxAgi;}
    public void setBaseMaxAgi(int baseMaxAgi) {this.baseMaxAgi = baseMaxAgi;}
    public int getBonusMaxAgi() {return bonusMaxAgi;}
    public void setBonusMaxAgi(int bonusMaxAgi) {this.bonusMaxAgi = bonusMaxAgi;}
    public int getTotalMaxAgi() {return totalMaxAgi;}
    public void setTotalMaxAgi(int totalMaxAgi) {this.totalMaxAgi = totalMaxAgi;}
    public Bag getBag() {return bag;}
    public void setBag(Bag bag) {this.bag = bag;}

}
